package hn.cch.spring.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.lang.NonNull;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

public class MethodInvocationImpl implements MethodInvocation {

    private final Object target;
    private final Method method;
    private final Object[] arguments;
    protected final List<MethodInterceptor> methodInterceptorList;
    private int currentInterceptorIndex = 0;

    public MethodInvocationImpl(Object target, Method method, Object[] arguments,
                                List<MethodInterceptor> methodInterceptorList) {
        this.target = target;
        this.method = method;
        this.arguments = arguments;
        this.methodInterceptorList = methodInterceptorList;
    }

    @NonNull
    @Override
    public Method getMethod() {
        return method;
    }

    @NonNull
    @Override
    public Object[] getArguments() {
        return arguments;
    }

    @NonNull
    @Override
    public Object getThis() {
        return target;
    }

    @NonNull
    @Override
    public AccessibleObject getStaticPart() {
        return method;
    }

    @NonNull
    @Override
    public Object proceed() throws Throwable {
        if (currentInterceptorIndex < methodInterceptorList.size()) {
            MethodInterceptor methodInterceptor = methodInterceptorList.get(currentInterceptorIndex++);
            return Objects.requireNonNull(methodInterceptor.invoke(this));
        } else {// 递归结束
            return method.invoke(target, arguments);
        }
    }
}
